#include <string.h>
#include <pthread.h>
#include <unistd.h>

#include "task.h"
#include "core_conf.h"
#include "log.h"
#include "task_manager.h"
#include "msg.h"
#include "mem.h"

struct task_manager;

extern struct core_conf core_conf;

struct task* get_task_by_tid(pthread_t tid)
{
	log_info("begin get_task_by_tid.");

	struct task_manager *task_manager = NULL;
	task_manager = core_conf.task_manager;

	if (task_manager == NULL) {
		log_warning("task_manager is NULL.");
		return NULL;
	}

	/* fixme:task_manager may be NULL now... */
//	pthread_mutex_lock(&(task_manager->lock));
	struct task *tmp;
	for (tmp = task_manager->task_head; tmp != NULL && tid != tmp->tid; tmp = tmp->next) {
		/* waitting... */
	}
//	pthread_mutex_unlock(&(task_manager->lock));

	return tmp;
}

struct task *get_task_by_name(char *name)
{
	log_info("begin get_task_by_name.");

	struct task_manager *task_manager = NULL;
	task_manager = core_conf.task_manager;

	if (task_manager == NULL || name == NULL) {
		log_warning("task_manager is NULL or name is NULL.");
		return NULL;
	}

	/* fixme:task_manager may be NULL now... */
//	pthread_mutex_lock(&(task_manager->lock));
	if (strcmp(name, "no name") == 0) {
		log_warning("we cann't get task 'no name'.");
		return NULL;
	}

	struct task *tmp;
	for (tmp = task_manager->task_head; tmp != NULL && strcmp(tmp->task_name, name) != 0; tmp = tmp->next) {
		/* waitting... */
	}
//	pthread_mutex_unlock(&(task_manager->lock));

	return tmp;
}

int register_task(struct task_manager *task_manager, struct task *task)
{
	log_info("begin register_task.");
	if (task_manager == NULL || task == NULL) {
		log_error("task_manager is NULL or task is NULL.");
		return -1;
	}
	
	return task_manager_add_task(task_manager, task);
}

int register_plugin_task(struct task_manager *task_manager, char *task_name, void *(*func)(void *), int (*msg_ops)(struct msg *))
{
	log_info("begin register_plugin_task.");
	log_print("-->begin register user mode task: %s", task_name != NULL ? task_name : "no name");
	if (task_manager == NULL || func == NULL) {
		log_error("task_manager is NULL or func is NULL.");
		return -1;
	}

	struct task *task = (struct task *)malloc(sizeof(struct task));
	if (task == NULL) {
		log_error("No enough Mem.");
		return -2;
	}

	if (task_name != NULL) {
		strncpy(task->task_name, task_name, TASK_NAME_MAX_LEN);
	} else {
		strncpy(task->task_name, "no name", TASK_NAME_MAX_LEN);
	}
	task->task_name[TASK_NAME_MAX_LEN - 1] = '\0';

	task->is_default = 1;
	task->func = func;
	task->msg_ops = msg_ops;
	task->next = NULL;
	task->task_manager = task_manager;
	task->db_ops = NULL;
	task->db_data = NULL;
	
	struct mm_struct *mm_struct = mm_struct_create();
	if (mm_struct == NULL) {
		log_error("cann't create mm_struct.");
		free(task);
		return -4;
	}
	task->mm = mm_struct;
	task->mm->task = task;

	struct msg_queue *msg_queue = NULL;
	msg_queue = msg_queue_create();
	if (msg_queue == NULL) {
		log_error("cann't init msg_queue");
		free(task->mm);
		free(task);
		return -3;
	}
	task->msg_queue_request = msg_queue;

	msg_queue = msg_queue_create();
	if (msg_queue == NULL) {
		free(task->msg_queue_request);
		free(task->mm);
		free(task);
		log_error("cann't init msg_queue");
		return -3;
	}
	task->msg_queue_result = msg_queue;

	log_print("-->register user mode task: %s successful.", task_name != NULL ? task_name : "no name");
	return register_task(task_manager, task);
}

int register_default_task(struct task_manager *task_manager, char *task_name, void *(*func)(void *), int (*msg_ops)(struct msg *))
{
	log_info("begin register_default_task.");
	log_print("-->begin register core mode task: %s", task_name != NULL ? task_name : "no name");
	if (task_manager == NULL || func == NULL) {
		log_error("task_manager is NULL or func is NULL.");
		return -1;
	}

	struct task *task = (struct task *)malloc(sizeof(struct task));
	if (task == NULL) {
		log_error("No enough Mem.");
		return -2;
	}

	if (task_name != NULL) {
		strncpy(task->task_name, task_name, TASK_NAME_MAX_LEN);
	} else {
		strncpy(task->task_name, "no name", TASK_NAME_MAX_LEN);
	}
	task->task_name[TASK_NAME_MAX_LEN - 1] = '\0';
	
	char pcap_socket[20];

	if(core_conf.pcap_mode==2)
	{
		strcpy(pcap_socket,"pcap_task");		
	}	
	else
	{
		strcpy(pcap_socket,"socket_task");
	}

	if(strcmp(task_name,pcap_socket)==0)
	{
		task->is_default = 0;
	}
	else
	{
		task->is_default = 1;
	}

	task->func = func;
	task->msg_ops = msg_ops;
	task->next = NULL;
	task->task_manager = task_manager;
	task->db_ops = NULL;
	task->db_data = NULL;

	struct mm_struct *mm_struct = mm_struct_create();
	if (mm_struct == NULL) {
		log_error("cann't create mm_struct.");
		free(task);
		return -4;
	}
	task->mm = mm_struct;
	task->mm->task = task;

	struct msg_queue *msg_queue = NULL;
	msg_queue = msg_queue_create();
	if (msg_queue == NULL) {
		log_error("cann't init msg_queue");
		free(task->mm);
		free(task);
		return -3;
	}
	task->msg_queue_request = msg_queue;

	msg_queue = msg_queue_create();
	if (msg_queue == NULL) {
		log_error("cann't init msg_queue");
		free(task->msg_queue_request);
		free(task->mm);
		free(task);
		return -3;
	}
	task->msg_queue_result = msg_queue;

	log_print("-->register core mode task: %s successful.", task_name != NULL ? task_name : "no name");
	return register_task(task_manager, task);
}

void start_default_task(struct core_conf *core_conf)
{
	log_info("begin start_default_task.");
	if (core_conf == NULL || core_conf->task_manager == NULL) {
		log_error("core_conf is NULL or task_manager is NULL.");
		return; 
	}

	pthread_mutex_lock(&(core_conf->task_manager->lock));
	struct task *task = core_conf->task_manager->task_head;

	for ( ; task != NULL; task = task->next)
	{
		if (task->func == NULL || task->is_default ==0) {
			log_warning("task: %s's func is NULL.", task->task_name);
		}
		else
		{
			int ret;
			ret = pthread_create(&task->tid, NULL, task->func, NULL);	
			if (ret != 0)
			{
				log_error("can't start task %s, ret = %d.", task->task_name, ret);
				continue;
			}

			if (task->is_default == 1)
			{
				log_info("start default task: %s.", task->task_name);
				log_print("start default task: %s.", task->task_name);
			}
		}
		/* for test */
		sleep(1);
	}
	pthread_mutex_unlock(&(core_conf->task_manager->lock));
}

